package com.unistec.fileserver.server.provider.fastdfs;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Properties;

import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.unistec.fileserver.client.entity.Resource;
import com.unistec.fileserver.server.biz.FileServerService;
import com.unistec.fileserver.server.enums.FileType;
import com.unistec.fileserver.server.provider.IResourceSearchProvider;
import com.unistec.fileserver.server.provider.IStorageProvider;
import com.unistec.framework.exception.NotifyException;
import com.unistec.framework.utils.FileUtils;
import com.unistec.framework.utils.Objects;
import com.unistec.framework.utils.SpringUtils;
import com.unistec.framework.utils.UUIDUtils;

public class LocalFastDFSStorageProvider implements IStorageProvider, IResourceSearchProvider {
	LocalFastDFSConfig config;

	public LocalFastDFSStorageProvider() {
		this.config = SpringUtils.getBean(LocalFastDFSConfig.class);
	}

	// 上传支持的文件类型
	private List<FileType> fileTypes;

	public List<FileType> getFileTypes() {
		return fileTypes;
	}

	public void setFileTypes(List<FileType> fileTypes) {
		this.fileTypes = fileTypes;
	}

	@Override
	public boolean exceedQuota(JSONObject extraParams, JSONObject params) {
		return false;
	}

	@Override
	public Resource uploadFile(JSONObject extraParams, String folder, File file, String fileName) throws Exception {
		return uploadFile(extraParams, file);
	}

	@Override
	public Resource uploadFile(JSONObject extraParams, String folder, File file) throws Exception {
		return uploadFile(extraParams, file);
	}

	@Override
	public Resource uploadFile(JSONObject extraParams, String folder, MultipartFile file) throws Exception {
		return uploadFile(extraParams, file);
	}

	@Override
	public Resource uploadFile(JSONObject extraParams, String folder, String filename, byte[] data) throws Exception {
		return uploadFile(extraParams, filename, data);
	}

	@Override
	public Resource uploadFile(JSONObject extraParams, File file, String fileName) throws Exception {
		return uploadFile(extraParams, file);
	}

	@Override
	public Resource uploadFile(JSONObject paramHolder, String folder, String filename, InputStream in) throws Exception {
		File tempFolder = FileUtils.TempDirectory.location();
		String name = FileUtils.createTempFileName(null, null, FileUtils.getUriExtention(filename));

		File tempFile = new File(tempFolder, name);
		FileUtils.saveInputStream(in, tempFile);

		return uploadFile(paramHolder, folder, tempFile, filename);
	}

	/**
	 * 上传文件
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 * @throws MyException
	 */
	@Override
	public Resource uploadFile(JSONObject extraParams, File file) throws Exception {
		NameValuePair[] params = jsonObjectNameValuePair(extraParams);
		String extName = FileUtils.getUriExtention(file.getPath());
		String[] results = getStorageClient().upload_file(file.getAbsolutePath(), extName, params);

		// 2. 当审核通过后，文件会被上传至CC
		String url = "/" + results[0] + "/" + results[1];

		return safeSetResource(extraParams, url, results);
	}

	/**
	 * 上传文件
	 * 
	 * @return
	 * @throws IOException
	 * @throws MyException
	 */
	@Override
	public Resource uploadFile(JSONObject extraParams, String filename, byte[] data) throws Exception {
		NameValuePair[] params = jsonObjectNameValuePair(extraParams);

		String extName = filename.substring(filename.lastIndexOf(".") + 1);
		String[] results = getStorageClient().upload_file(data, extName, params);

		// 2. 当审核通过后，文件会被上传至CC
		String url = "/" + results[0] + "/" + results[1];

		return safeSetResource(extraParams, url, results);
	}

	/**
	 * 上传文件
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 * @throws MyException
	 */
	@Override
	public Resource uploadFile(JSONObject extraParams, MultipartFile file) throws Exception {
		String fileName = Objects.isNull(file.getOriginalFilename()) ? file.getName() : file.getOriginalFilename();
		return uploadFile(extraParams, fileName, file.getBytes());
	}

	/**
	 * 上传文件
	 * 
	 * @param bytes
	 * @param fileName
	 * @return
	 * @throws IOException
	 * @throws MyException
	 */
	public String[] uploadFile(byte[] bytes, String fileName) throws IOException, MyException {
		String extName = fileName.substring(fileName.lastIndexOf(".") + 1);
		return getStorageClient().upload_file(bytes, extName, null);
	}

	/**
	 * 安全保存文件
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-29
	 * @time 14:38:11
	 * 
	 * @param paramHolder
	 * @param url
	 * @param results
	 * @return
	 */
	Resource safeSetResource(JSONObject paramHolder, String url, String[] results) {
		Resource uf = null;
		if (paramHolder.containsKey("asyncUpload") && paramHolder.getBooleanValue("asyncUpload") && paramHolder.containsKey("resourceId")) {
			// 异步上传
			FileServerService fs = SpringUtils.getBean(FileServerService.class);
			uf = fs.selectById("resourceId");
			if (uf != null) {

				uf.setUrl(url);
				uf.setForeignIdentity(JSON.toJSONString(results));
				uf.setStorageType(this.getClass().getName());
				fs.updateById(uf);
			}
		} else {
			uf = new Resource();
			uf.setFileId(UUIDUtils.get32UUID());
			uf.setUrl(url);
			uf.setForeignIdentity(JSON.toJSONString(results));
			uf.setStorageType(this.getClass().getName());
		}
		return uf;
	}

	/**
	 * 获取StorageClient
	 * 
	 * @return
	 * @throws IOException
	 * @throws MyException
	 */
	public StorageClient getStorageClient() throws IOException, MyException {
		LocalFastDFSConfig config = SpringUtils.getBean(LocalFastDFSConfig.class);
		Properties p = new Properties();
		p.setProperty("fastdfs.tracker_servers", config.getTrackerServers());

		// 初始化全局配置，加载配置文件。
		ClientGlobal.initByProperties(p); // tracker_server=www.zjlll.net:22122

		// 创建TrackerClient对象。
		TrackerClient trackerClient = new TrackerClient();

		// 创建TrackerServer对象。
		TrackerServer trackerServer = trackerClient.getConnection();

		// 声明StorageServer对象，null。
		StorageServer storageServer = null;

		// 获得StorageClient对象。
		return new StorageClient(trackerServer, storageServer);
	}

	/**
	 * 删除文件
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-29
	 * @time 12:58:51
	 * 
	 * @param paramHolder
	 * @param f
	 * @param fileName
	 * @return
	 * @throws Exception
	 */
	public boolean deleteFile(JSONObject params, String url) throws Exception {
		int idxStart = url.indexOf("/group");
		String subUrl = url.substring(idxStart + 1);
		idxStart = subUrl.indexOf("/");
		String groupName = subUrl.substring(0, idxStart);
		String sufixUrl = subUrl.substring(idxStart);
		int result = getStorageClient().delete_file(groupName, sufixUrl);
		return result == 0;
	}

	/**
	 * 判断文件是否存在
	 * 
	 * @description
	 * @author 胡晓光
	 * @date 2021-9-29
	 * @time 12:59:18
	 * 
	 * @param paramHolder
	 * @param fileName
	 * @return
	 * @throws Exception
	 */
	@Override
	public boolean existFile(JSONObject extraParams, String url) throws Exception {
		int idxStart = url.indexOf("/group");
		String subUrl = url.substring(idxStart + 1);
		idxStart = subUrl.indexOf("/");
		String groupName = subUrl.substring(0, idxStart);
		String sufixUrl = subUrl.substring(idxStart);
		return null != getStorageClient().get_file_info(groupName, sufixUrl);
	}

	@Override
	public List<Resource> searchResource(JSONObject params, PageInfo<Resource> pageInfo) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Resource> getResourceInfoByForeignStorageId(List<String> foreignIds) {
		return null;
	}

	@Override
	public List<Resource> getResourceInfoByUrl(List<String> urls) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Resource getResourceInfoByUnique(String unique) {
		return null;
	}

	@Override
	public InputStream getFileInputStream(Resource resource) {
		try {
			String strUrl = config.getWeburl() + resource.getUrl();
			URL url = new URL(strUrl);
			URLConnection urlConnection = url.openConnection();
			return urlConnection.getInputStream();
		} catch (Exception e) {
			throw new NotifyException("文件不存在，下载失败！");
		}
	}

	@Override
	public InputStream getFileInputStream(String path) {
		throw new NotifyException("Unsupport in FASTDFS implementation");
	}
}